package commons.dao.impl;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.transaction.annotation.Transactional;

import commons.dao.GenericDao;
import commons.model.BaseEntity;

/**
 * Provides generic common implementation of GenericDao interface persistence methods
 * Extend this abstract class to implement DAO for your specific needs.
 * @author giandefi
 *
 */
@Transactional
public abstract class GenericDaoImpl<T, ID extends Serializable> implements GenericDao<T, ID>{

	private Class<T> persistentClass;
	private EntityManager entityManager;
	
	public GenericDaoImpl(Class<T> persistentClass)
	{
		this.persistentClass = persistentClass;
	}
	
	
	protected EntityManager getEntityManager() {
		return entityManager;
	}

	@PersistenceContext
	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}


	public Class<T> getPersistentClass() {
		return persistentClass;
	}
	
	 @Transactional(readOnly=true)
     public T findById(ID id) {
             T entity = (T) getEntityManager().find(getPersistentClass(), id);
             return entity;
     }
    
     @SuppressWarnings("unchecked")
	@Transactional(readOnly=true)
     public List<T> findAll() {
             return getEntityManager()
                     .createQuery("select x from " + getPersistentClass().getSimpleName() + " x")
                     .getResultList();
     }
    
     public T save(T entity) {
             getEntityManager().persist(entity);
             return entity;
     }
    
     public T update(T entity) {
             T mergedEntity = getEntityManager().merge(entity);
             return mergedEntity;
     }
    
     public void delete(T entity) {
             if (BaseEntity.class.isAssignableFrom(persistentClass)) {
                     getEntityManager().remove(
                                     getEntityManager().getReference(entity.getClass(),
                                                     ((BaseEntity)entity).getId()));
             } else {
                     entity = getEntityManager().merge(entity);
                     getEntityManager().remove(entity);
             }
     }
    
     public void flush() {
             getEntityManager().flush();
     }
    
	
}
